package com.eastfair.projectcore.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.annotation.annotation.cache.Cache;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.entity.OrganizationRole;
import com.eastfair.auth.entity.UserAccount;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperCacheServiceImpl;
import com.eastfair.cache.common.DictionaryTypeCacheKeyBuilder;
import com.eastfair.cache.projectcore.DictionaryCacheKeyBuilder;
import com.eastfair.cache.projectcore.DictionaryEnabledCacheKeyBuilder;
import com.eastfair.cache.projectcore.FormFieldCacheKeyBuilder;
import com.eastfair.cache.repository.CacheOps;
import com.eastfair.cache.repository.CachePlusOps;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.model.CacheHashKey;
import com.eastfair.core.model.CacheKey;
import com.eastfair.core.model.CacheKeyBuilder;

import com.eastfair.core.utils.CollHelper;
import com.eastfair.database.mybatis.conditions.Wraps;
import com.eastfair.database.mybatis.conditions.query.LbqWrapper;
import com.eastfair.projectcore.dao.DictionaryMapper;
import com.eastfair.projectcore.dto.DictionaryPageQuery;
import com.eastfair.projectcore.entity.Dictionary;
import com.eastfair.projectcore.entity.Menu;
import com.eastfair.projectcore.enumeration.MenuSceneEnum;
import com.eastfair.projectcore.service.DictionaryService;
import com.eastfair.boot.service.SuperServiceImpl;

import com.eastfair.projectcore.service.MenuService;
import com.eastfair.uid.baidu.rule.SnowFlakeRole;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 字典项
 * </p>
 *
 * @author ligang
 * @date 2021-11-01
 */
@Slf4j
@Service
public class DictionaryServiceImpl extends SuperCacheServiceImpl<DictionaryMapper, Dictionary> implements DictionaryService {
    @Autowired
    private CachePlusOps cachePlusOps;
    @Autowired
    CacheOps cacheOps;
    @Autowired
    private MenuService menuService;
    @Autowired
    SnowFlakeRole snowFlakeRole;
    @Override
    public CacheKeyBuilder getCacheKeyBuilder() {
        return new DictionaryCacheKeyBuilder();
    }

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(Dictionary model) {
        model.setId(snowFlakeRole.findUidSimple());
        //删除缓存
        CacheHashKey typeKey = new DictionaryCacheKeyBuilder().hashFieldKey(model.getType(), Dictionary.class.getName());
        cachePlusOps.hDel(typeKey);
        //清空字典按需返回缓存
        removeDictCache(model.getType());
        //雪花ID,不需要分库分表
//        SelfUidDto selfUidDto = new SelfUidDto();
//        model.setId(selfUidService.getUid(selfUidDto));
        if (model.getSequence() == null) {
            //默认排序
            model.setSequence(querySort(model.getType()));
        }
        return R.successDef();
    }

    /**
     * 清空字典按需返回缓存
     *
     * @param type
     */
    public void removeDictCache(String type) {
        CacheHashKey typeKey = new DictionaryEnabledCacheKeyBuilder().hashFieldKey(type, type);
        Set<String> keys = cachePlusOps.keys(typeKey.getKey() + ":*");
        if (CollectionUtil.isNotEmpty(keys)) {
            String[] s2 = new String[keys.size()];
            int num = 0;
            for (String s : keys) {
                s2[num++] = s;
            }
            log.info("删除缓存 key is {}", s2);
            cachePlusOps.del(s2);

        }
    }

    /**
     * 处理修改相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerUpdateById(Dictionary model) {
        //删除缓存
        CacheHashKey typeKey = new DictionaryCacheKeyBuilder().hashFieldKey(model.getType(), Dictionary.class.getName());
        cachePlusOps.hDel(typeKey);
        //清空字典按需返回缓存
        removeDictCache(model.getType());
        return R.successDef();
    }


    public int querySort(String type) {
        if (StringUtils.isBlank(type)) {
            return 1;
        }
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        queryWrapper.lambda().eq(Dictionary::getType, type);
        //查询用户
        List<Dictionary> dictionaryList = list(queryWrapper);
        if (dictionaryList != null && !dictionaryList.isEmpty()) {
            int max = dictionaryList.stream().mapToInt(s -> s.getSequence()).max().getAsInt();
            return max + 1;
        }
        return 1;
    }

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<Dictionary> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
            //删除类型缓存
            CacheHashKey typeKey = new DictionaryCacheKeyBuilder().hashFieldKey(s.getType(), Dictionary.class.getName());
            cachePlusOps.del(typeKey);
            //清空字典按需返回缓存
            removeDictCache(s.getType());
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等

        return R.successDef();
    }


    @Override
    public List<Dictionary> queryDict(String type) {
        if (StringUtils.isBlank(type)) {
            return null;
        }
        CacheHashKey typeKey = new DictionaryCacheKeyBuilder().hashFieldKey(type, Dictionary.class.getName());
        List<Dictionary> result = cachePlusOps.hGet(typeKey);
        if (result == null || result.isEmpty()) {
            Dictionary dictionary = new Dictionary();
            dictionary.setType(type);
            List<Dictionary> list = list(dictionary, null);
            if (list != null && !list.isEmpty()) {
                cachePlusOps.hSet(typeKey, list);
            }
            return list;
        }
        return result;
    }

    @Override
    public List<Dictionary> queryDictGroupType() {
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        queryWrapper.groupBy("label", "type").select("label", "type");
        List<Dictionary> dictionaryList = list(queryWrapper);
        return dictionaryList;
    }

    @Override
    public void initDictData() {
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        List<Dictionary> list = list(queryWrapper);
        Map<String, List<Dictionary>> groupList = list.stream().collect(Collectors.groupingBy(Dictionary::getType));
        for (String key : groupList.keySet()) {
            CacheHashKey typeKey = new DictionaryCacheKeyBuilder().hashFieldKey(key, Dictionary.class.getName());
            cachePlusOps.hSet(typeKey, groupList.get(key));
        }
    }

    @Override
    public void delType(String type) {
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        //是管理菜单，则不考虑子系统
        queryWrapper.lambda().eq(Dictionary::getType, type);
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        remove(queryWrapper);
    }

    //    @Cache(expire = 60, key = "#hash(#args)")
    @Override
    public List<Dictionary> listByIds(List<Long> ids) {
        return list(null, ids);
    }


    //    @Cache(expire = 60, key = "#hash(#args)")
    @Override
    public List<Dictionary> listByIds2(List<Long> ids, DictionaryPageQuery dictionaryPageQuery) {
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        queryWrapper.lambda().in(Dictionary::getId, ids);
        return list(queryWrapper);
    }

    //    @Cache(expire = 600,
//            key = "#hash(#args[0])"
////            key = "#{dictionaryService.cacheKeyBuilder().getPrefix()}"
//    )
    @Override
    public List<Dictionary> listByObject(DictionaryPageQuery dictionaryPageQuery) {
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        if (dictionaryPageQuery != null) {
            if (StringUtils.isNotBlank(dictionaryPageQuery.getName())) {
                queryWrapper.lambda().in(Dictionary::getName, dictionaryPageQuery.getName());
            }
            if (StringUtils.isNotBlank(dictionaryPageQuery.getType())) {
                queryWrapper.lambda().in(Dictionary::getType, dictionaryPageQuery.getType());
            }
        }
        return list(queryWrapper);
    }

    @Override
    public List<Dictionary> list(Dictionary dictionary, List<Long> ids) {
        if (dictionary != null && dictionary.getIsEnabled() == null) {
            dictionary.setIsEnabled(BusinessConstant.DELETE_YES);
        }
        return ((DictionaryService) AopContext.currentProxy()).listOfCache(dictionary, ids);
    }

    @Override
//    @Cache(key = "#hash(#args[0])")
    public List<Dictionary> list2(Dictionary dictionary, List<Long> ids) {
        //查询
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        if (dictionary != null) {
            if (dictionary.getId() != null) {
                queryWrapper.lambda().eq(Dictionary::getId, dictionary.getId());
            }
            if (StringUtils.isNotBlank(dictionary.getType())) {
                queryWrapper.lambda().eq(Dictionary::getType, dictionary.getType());
            }
            if (StringUtils.isNotBlank(dictionary.getLabel())) {
                queryWrapper.lambda().like(Dictionary::getLabel, "%" + dictionary.getLabel() + "%");
            }

            if (StringUtils.isNotBlank(dictionary.getName())) {
                queryWrapper.lambda().eq(Dictionary::getName, dictionary.getName());
            }

            if (StringUtils.isNotBlank(dictionary.getCode())) {
                queryWrapper.lambda().eq(Dictionary::getCode, dictionary.getCode());
            }


            if (dictionary.getTypeId() != null) {
                queryWrapper.lambda().eq(Dictionary::getTypeId, dictionary.getTypeId());
            }
        }
        if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(Dictionary::getId, ids);
        }
        queryWrapper.lambda().eq(Dictionary::getIsEnabled, BusinessConstant.DELETE_YES);
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        return list(queryWrapper);
    }

    @Override
//    @Cache(key = "",
//            magic = @Magic(
//                    key = "{{'id', #args[0]?.id},{'type', #args[0]?.type}," +
//                            "{'name', #args[0]?.name},{'code', #args[0]?.code}," +
//                            "{'label', #args[0]?.label,'like'},{'id', #args[1]}}"))
    public List<Dictionary> list3(Dictionary dictionary, List<Long> ids) {
        //查询
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        if (dictionary != null) {
            if (dictionary.getId() != null) {
                queryWrapper.lambda().eq(Dictionary::getId, dictionary.getId());
            }
            if (StringUtils.isNotBlank(dictionary.getType())) {
                queryWrapper.lambda().eq(Dictionary::getType, dictionary.getType());
            }
            if (StringUtils.isNotBlank(dictionary.getLabel())) {
                queryWrapper.lambda().like(Dictionary::getLabel, "%" + dictionary.getLabel() + "%");
            }

            if (StringUtils.isNotBlank(dictionary.getName())) {
                queryWrapper.lambda().eq(Dictionary::getName, dictionary.getName());
            }

            if (StringUtils.isNotBlank(dictionary.getCode())) {
                queryWrapper.lambda().eq(Dictionary::getCode, dictionary.getCode());
            }


            if (dictionary.getTypeId() != null) {
                queryWrapper.lambda().eq(Dictionary::getTypeId, dictionary.getTypeId());
            }
        }
        if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(Dictionary::getId, ids);
        }
        queryWrapper.lambda().eq(Dictionary::getIsEnabled, BusinessConstant.DELETE_YES);
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        return list(queryWrapper);
    }

    @Override
    @Cache(key = "",
            magic = @Magic(
                    key = "{{'id', #args[0]?.id},{'type', #args[0]?.type},{'name', #args[0]?.name},{'code', #args[0]?.code}," +
                            "{'label', #args[0]?.label,'like'},{'typeId', #args[0]?.typeId},{'isEnabled', #args[0]?.isEnabled},{'id', #args[1]}}"))
    public List<Dictionary> listOfCache(Dictionary dictionary, List<Long> ids) {
        //查询
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        if (dictionary != null) {
            if (dictionary.getId() != null) {
                queryWrapper.lambda().eq(Dictionary::getId, dictionary.getId());
            }
            if (StringUtils.isNotBlank(dictionary.getType())) {
                queryWrapper.lambda().eq(Dictionary::getType, dictionary.getType());
            }
            if (StringUtils.isNotBlank(dictionary.getLabel())) {
                queryWrapper.lambda().like(Dictionary::getLabel, "%" + dictionary.getLabel() + "%");
            }

            if (StringUtils.isNotBlank(dictionary.getName())) {
                queryWrapper.lambda().eq(Dictionary::getName, dictionary.getName());
            }

            if (StringUtils.isNotBlank(dictionary.getCode())) {
                queryWrapper.lambda().eq(Dictionary::getCode, dictionary.getCode());
            }
            if (dictionary.getTypeId() != null) {
                queryWrapper.lambda().eq(Dictionary::getTypeId, dictionary.getTypeId());
            }

            if (dictionary.getIsEnabled() != null) {
                queryWrapper.lambda().eq(Dictionary::getIsEnabled, dictionary.getIsEnabled());
            }
        }
        if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(Dictionary::getId, ids);
        }

        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        return list(queryWrapper);
    }


    @Override
//    @Cache(key = "#hash(#args)")
    public R<IPage<Dictionary>> pageVo(PageParams<Dictionary> params) {
        Dictionary dictionary = params.getModel();
        //查询
        QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
        if (dictionary != null) {
            if (dictionary.getId() != null) {
                queryWrapper.lambda().eq(Dictionary::getId, dictionary.getId());
            }
            if (StringUtils.isNotBlank(dictionary.getType())) {
                queryWrapper.lambda().eq(Dictionary::getType, dictionary.getType());
            }

            if (StringUtils.isNotBlank(dictionary.getName())) {
                queryWrapper.lambda().eq(Dictionary::getName, dictionary.getName());
            }
        }
        queryWrapper.lambda().eq(Dictionary::getIsEnabled, BusinessConstant.DELETE_YES);
        queryWrapper.lambda().eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO);
        Page<Dictionary> servePage = new Page<>(params.getCurrent(), params.getSize());
        IPage<Dictionary> dictionaryIPage = page(servePage, queryWrapper);
        return R.success(dictionaryIPage);
    }

    @Override
    public Map<Serializable, Object> findNameByIds(Set<Serializable> set) {
        return null;
    }

    @Override
    public Map<Serializable, Object> findByIds(Set<Serializable> codes) {
        if (codes.isEmpty()) {
            return Collections.emptyMap();
        }
        List<Dictionary> dictionaryList = codes.stream().map(code -> {
            QueryWrapper<Dictionary> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(Dictionary::getIsDeleted, BusinessConstant.DELETE_NO)
                    .eq(Dictionary::getCode, code);

            return getOne(queryWrapper);
        }).collect(Collectors.toList());

        return CollHelper.uniqueIndex(dictionaryList, Dictionary::getCode, Dictionary::getName);
    }


}
